﻿#pragma once
/*
#include <cstring>
#include <mbstring.h>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include<windows.h>
#include<Wininet.h>
#include<string>
#include<tchar.h>
*/
#include "stdafx.h"
#include <winsock2.h>
#include <conio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <objbase.h>
#include <stdio.h>
#include <assert.h>
#pragma comment(lib, "wsock32.lib") 


using namespace std;

//array<System::Byte> ^ObjectToByteArray(System::Object ^_Object);
array<unsigned char>^ ObjectToByteArray(System::Object ^_Object);



//get handler to use
HWND hwnd, hwnd2;//GetDesktopWindow();//::GetForegroundWindow(); // 得到活动的窗体
RECT rect, rect2;
int w, w2;
int h, h2;	
// 下面这段查MSDN的BitBlt函数，后面有一个 Capturing an Image，大致有下面一段
HDC hdc, hdc2;	
HDC hdcCompatible, hdcCompatible2;
HBITMAP	hbm, hbm2;
unsigned char data[320*240*4], data2[320*240*4];
unsigned char data1[320*240*3/2], data3[320*240*3/2];
BITMAPINFO infoHeader, infoHeader2;


namespace AMC_Demo {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Form1 的摘要
	/// </summary>

	// Define struct to hold image data
	struct AnalysisData
	{
		unsigned char* ImgData;
	};
	AnalysisData ImageData;


	public ref class Form1 : public System::Windows::Forms::Form
	{

	public:
		//Setup for getting current image of axAxisMediaControl
		int theFormat;// 0=jpeg 1=BMP
		Object^ theImgBuffer;
		Object^ theImgBuffer2;
		__int32 theBufferSize;

		int imgWidth;
		int imgHeight;
	private: AxAXISMEDIACONTROLLib::AxAxisMediaControl^  AMC2;
	public: 
	private: System::Windows::Forms::PictureBox^  pictureBox2;

	public: 

	public: 

			 unsigned char *imageDataRGB, *imageDataRGB2;

		Form1(void)
		{
			InitializeComponent();

			theFormat = 1;// 0=jpeg 1=BMP
			theImgBuffer = gcnew Object();
			theImgBuffer2 = gcnew Object();
			theBufferSize = 0;

			this->imgHeight = 240;
			this->imgWidth = 320;
			this->imageDataRGB = new unsigned char[3*imgWidth*imgHeight];
			this->imageDataRGB2 = new unsigned char[3*imgWidth*imgHeight];

			//
			//TODO: 在此加入建構函式程式碼
			//
		}

	protected:
		/// <summary>
		/// 清除任何使用中的資源。
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}

	private: AxAXISMEDIACONTROLLib::AxAxisMediaControl^  AMC;
	private: System::Windows::Forms::Button^  buttonPlay;
	private: System::Windows::Forms::Button^  buttonStop;
	private: System::Windows::Forms::Button^  buttonInitial;
	private: System::Windows::Forms::Button^  buttonLiveShow;
	private: System::Windows::Forms::Button^  buttonSlowShow;

	private: System::ComponentModel::BackgroundWorker^  backgroundWorker1;
	private: System::ComponentModel::BackgroundWorker^  backgroundWorker2;
	private: System::Windows::Forms::PictureBox^  pictureBox1;

	private:
		/// <summary>
		/// 設計工具所需的變數。
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// 此為設計工具支援所需的方法 - 請勿使用程式碼編輯器
		/// 修改這個方法的內容。
		/// </summary>
		void InitializeComponent(void)
		{
			System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));
			this->buttonPlay = (gcnew System::Windows::Forms::Button());
			this->buttonStop = (gcnew System::Windows::Forms::Button());
			this->AMC = (gcnew AxAXISMEDIACONTROLLib::AxAxisMediaControl());
			this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
			this->buttonSlowShow = (gcnew System::Windows::Forms::Button());
			this->backgroundWorker1 = (gcnew System::ComponentModel::BackgroundWorker());
			this->backgroundWorker2 = (gcnew System::ComponentModel::BackgroundWorker());
			this->buttonInitial = (gcnew System::Windows::Forms::Button());
			this->buttonLiveShow = (gcnew System::Windows::Forms::Button());
			this->AMC2 = (gcnew AxAXISMEDIACONTROLLib::AxAxisMediaControl());
			this->pictureBox2 = (gcnew System::Windows::Forms::PictureBox());
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->AMC))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->AMC2))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox2))->BeginInit();
			this->SuspendLayout();
			// 
			// buttonPlay
			// 
			this->buttonPlay->Location = System::Drawing::Point(29, 504);
			this->buttonPlay->Name = L"buttonPlay";
			this->buttonPlay->Size = System::Drawing::Size(75, 23);
			this->buttonPlay->TabIndex = 1;
			this->buttonPlay->Text = L"PLAY";
			this->buttonPlay->UseVisualStyleBackColor = true;
			this->buttonPlay->Click += gcnew System::EventHandler(this, &Form1::buttonPlay_Click);
			// 
			// buttonStop
			// 
			this->buttonStop->Location = System::Drawing::Point(110, 504);
			this->buttonStop->Name = L"buttonStop";
			this->buttonStop->Size = System::Drawing::Size(75, 23);
			this->buttonStop->TabIndex = 2;
			this->buttonStop->Text = L"STOP";
			this->buttonStop->UseVisualStyleBackColor = true;
			this->buttonStop->Click += gcnew System::EventHandler(this, &Form1::buttonStop_Click);
			// 
			// AMC
			// 
			this->AMC->Enabled = true;
			this->AMC->Location = System::Drawing::Point(29, 12);
			this->AMC->Name = L"AMC";
			this->AMC->OcxState = (cli::safe_cast<System::Windows::Forms::AxHost::State^  >(resources->GetObject(L"AMC.OcxState")));
			this->AMC->Size = System::Drawing::Size(320, 240);
			this->AMC->TabIndex = 4;
			// 
			// pictureBox1
			// 
			this->pictureBox1->Location = System::Drawing::Point(355, 12);
			this->pictureBox1->Name = L"pictureBox1";
			this->pictureBox1->Size = System::Drawing::Size(320, 240);
			this->pictureBox1->TabIndex = 6;
			this->pictureBox1->TabStop = false;
			// 
			// buttonSlowShow
			// 
			this->buttonSlowShow->Location = System::Drawing::Point(360, 504);
			this->buttonSlowShow->Name = L"buttonSlowShow";
			this->buttonSlowShow->Size = System::Drawing::Size(75, 23);
			this->buttonSlowShow->TabIndex = 7;
			this->buttonSlowShow->Text = L"SlowShow";
			this->buttonSlowShow->UseVisualStyleBackColor = true;
			this->buttonSlowShow->Click += gcnew System::EventHandler(this, &Form1::buttonSlowShow_Click);
			// 
			// backgroundWorker1
			// 
			this->backgroundWorker1->WorkerSupportsCancellation = true;
			this->backgroundWorker1->DoWork += gcnew System::ComponentModel::DoWorkEventHandler(this, &Form1::backgroundWorker1_DoWork);
			// 
			// backgroundWorker2
			// 
			this->backgroundWorker2->WorkerSupportsCancellation = true;
			this->backgroundWorker2->DoWork += gcnew System::ComponentModel::DoWorkEventHandler(this, &Form1::backgroundWorker2_DoWork);
			// 
			// buttonInitial
			// 
			this->buttonInitial->Location = System::Drawing::Point(190, 504);
			this->buttonInitial->Name = L"buttonInitial";
			this->buttonInitial->Size = System::Drawing::Size(75, 23);
			this->buttonInitial->TabIndex = 9;
			this->buttonInitial->Text = L"Initial";
			this->buttonInitial->UseVisualStyleBackColor = true;
			this->buttonInitial->Click += gcnew System::EventHandler(this, &Form1::buttonInitial_Click);
			// 
			// buttonLiveShow
			// 
			this->buttonLiveShow->Location = System::Drawing::Point(441, 504);
			this->buttonLiveShow->Name = L"buttonLiveShow";
			this->buttonLiveShow->Size = System::Drawing::Size(75, 23);
			this->buttonLiveShow->TabIndex = 10;
			this->buttonLiveShow->Text = L"LiveShow";
			this->buttonLiveShow->UseVisualStyleBackColor = true;
			this->buttonLiveShow->Click += gcnew System::EventHandler(this, &Form1::buttonLiveShow_Click);
			// 
			// AMC2
			// 
			this->AMC2->Enabled = true;
			this->AMC2->Location = System::Drawing::Point(29, 258);
			this->AMC2->Name = L"AMC2";
			this->AMC2->OcxState = (cli::safe_cast<System::Windows::Forms::AxHost::State^  >(resources->GetObject(L"AMC2.OcxState")));
			this->AMC2->Size = System::Drawing::Size(320, 240);
			this->AMC2->TabIndex = 11;
			// 
			// pictureBox2
			// 
			this->pictureBox2->Location = System::Drawing::Point(355, 258);
			this->pictureBox2->Name = L"pictureBox2";
			this->pictureBox2->Size = System::Drawing::Size(320, 240);
			this->pictureBox2->TabIndex = 12;
			this->pictureBox2->TabStop = false;
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(838, 545);
			this->Controls->Add(this->pictureBox2);
			this->Controls->Add(this->AMC2);
			this->Controls->Add(this->buttonLiveShow);
			this->Controls->Add(this->buttonInitial);
			this->Controls->Add(this->buttonSlowShow);
			this->Controls->Add(this->pictureBox1);
			this->Controls->Add(this->AMC);
			this->Controls->Add(this->buttonStop);
			this->Controls->Add(this->buttonPlay);
			this->Name = L"Form1";
			this->Text = L"Form1";
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->AMC))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox1))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->AMC2))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBox2))->EndInit();
			this->ResumeLayout(false);

		}
#pragma endregion

	private: System::Void buttonPlay_Click(System::Object^  sender, System::EventArgs^  e) {
				 //Setup Controller information
				 AMC->MediaURL = "http://192.168.1.175/mjpg/video.mjpg";
				 AMC->MediaType = "BMP";
				 AMC->Play();

				 AMC2->MediaURL = "http://192.168.1.73/mjpg/video.mjpg";
				 AMC2->MediaType = "BMP";
				 AMC2->Play();

			 }
	private: System::Void buttonStop_Click(System::Object^  sender, System::EventArgs^  e) {
				 AMC->Stop();

				 AMC2->Stop();
			 }

	private: System::Void buttonSlowShow_Click(System::Object^  sender, System::EventArgs^  e) {
				 this->backgroundWorker1->RunWorkerAsync();				 
			 }

	private: System::Void buttonLiveShow_Click(System::Object^  sender, System::EventArgs^  e) {
				 this->backgroundWorker2->RunWorkerAsync();				 
			 }

	private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {

		while(1){

			//Sleep(20);
			// Get current image of axAxisMediaControl1
			AMC->GetCurrentImage(1, theImgBuffer, theBufferSize);
			AMC2->GetCurrentImage(1, theImgBuffer2, theBufferSize);

			array<unsigned char>^ ByteArray = ObjectToByteArray(theImgBuffer);
			array<unsigned char>^ ByteArray2 = ObjectToByteArray(theImgBuffer2);
				 
			for ( int j=0; j < 240 ; j++){
			for ( int i = 0 ; i < 320 ; i++){

				if ( i >= 26 )
				{
					imageDataRGB[(j*320+i-26)*3+0] = ByteArray[((239-j)*320+i)*3+2];
					imageDataRGB[(j*320+i-26)*3+1] = ByteArray[((239-j)*320+i)*3+0];
					imageDataRGB[(j*320+i-26)*3+2] = ByteArray[((239-j)*320+i)*3+1];

					imageDataRGB2[(j*320+i-26)*3+0] = ByteArray2[((239-j)*320+i)*3+2];
					imageDataRGB2[(j*320+i-26)*3+1] = ByteArray2[((239-j)*320+i)*3+0];
					imageDataRGB2[(j*320+i-26)*3+2] = ByteArray2[((239-j)*320+i)*3+1];
				}
				else if (  i>= 0 )
				{
					imageDataRGB[(j*320+i+294)*3+0] = ByteArray[((239-j)*320+i)*3+2];
					imageDataRGB[(j*320+i+294)*3+1] = ByteArray[((239-j)*320+i)*3+0];
					imageDataRGB[(j*320+i+294)*3+2] = ByteArray[((239-j)*320+i)*3+1];

					imageDataRGB2[(j*320+i+294)*3+0] = ByteArray2[((239-j)*320+i)*3+2];
					imageDataRGB2[(j*320+i+294)*3+1] = ByteArray2[((239-j)*320+i)*3+0];
					imageDataRGB2[(j*320+i+294)*3+2] = ByteArray2[((239-j)*320+i)*3+1];
				}					
			}


			}
			/*
			for (int i = 0; i < 320*240; i++) 
				memmove( imageDataRGB+ i*3, imageDataRGB + i*4, 3);
				*/

			this->pictureBox1->Image = gcnew System::Drawing::Bitmap(
				320,
				241,
				320*3,
				System::Drawing::Imaging::PixelFormat::Format24bppRgb,
				System::IntPtr(imageDataRGB)
				);

			this->pictureBox2->Image = gcnew System::Drawing::Bitmap(
				320,
				241,
				320*3,
				System::Drawing::Imaging::PixelFormat::Format24bppRgb,
				System::IntPtr(imageDataRGB2)
				);

		}

		}

	private: System::Void backgroundWorker2_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {

				 while(1){
					 Sleep(10);

					 ::BitBlt(hdcCompatible, 0, 0, w, h, hdc, 0, 0, SRCCOPY); 
					 ::GetDIBits(hdcCompatible, hbm, 0, h, data, &infoHeader, DIB_RGB_COLORS);

					 ::BitBlt(hdcCompatible2, 0, 0, w2, h2, hdc2, 0, 0, SRCCOPY); 
					 ::GetDIBits(hdcCompatible2, hbm2, 0, h2, data2, &infoHeader2, DIB_RGB_COLORS);

					 // 上面infoHeader.bmiHeader.biBitCount值是32，所以出来的数据一个像素占4个自己，顺序是BGRA
					 // 下面两行转成BGR24
					 for (int i = 0; i < w*h; i++){
						 memmove(data + i*3, data + i*4, 3);	
						 memmove(data2 + i*3, data2 + i*4, 3);	
					 }

					 // 数据是倒着的，下面倒回来
// 					 for (int i = 0; i < h/2; i++)
// 					 {
// 						 memcpy(data1, data + i*w*3, w*3);
// 						 memcpy(data + i*w*3, data + (h-i-1)*w*3, w*3);
// 						 memcpy(data + (h-i-1)*w*3, data1, w*3);
// 
// 						 memcpy(data3, data2 + i*w*3, w*3);
// 						 memcpy(data2 + i*w*3, data2 + (h-i-1)*w*3, w*3);
// 						 memcpy(data2 + (h-i-1)*w*3, data3, w*3);
// 					 }

					 this->pictureBox1->Image = gcnew System::Drawing::Bitmap(
						 320,
						 240,
						 320*3,
						 System::Drawing::Imaging::PixelFormat::Format24bppRgb,
						 System::IntPtr(data)
						 );

					 this->pictureBox2->Image = gcnew System::Drawing::Bitmap(
						 320,
						 240,
						 320*3,
						 System::Drawing::Imaging::PixelFormat::Format24bppRgb,
						 System::IntPtr(data2)
						 );
				 }

			 
			 }

private: System::Void buttonInitial_Click(System::Object^  sender, System::EventArgs^  e) {
			 // Get current image of axAxisMediaControl1
			 AMC->SaveCurrentImage(1,"hi.bmp");
			 AMC->GetCurrentImage(1, theImgBuffer, theBufferSize);

			 AMC2->SaveCurrentImage(1,"hi.bmp");
			 AMC2->GetCurrentImage(1, theImgBuffer, theBufferSize);

			 //use handler
			 hwnd = (HWND)AMC->Handle.ToInt32();//GetDesktopWindow();//::GetForegroundWindow(); // 得到活动的窗体
			 hwnd2 = (HWND)AMC2->Handle.ToInt32();//GetDesktopWindow();//::GetForegroundWindow(); // 得到活动的窗体
			 
			 //RECT rect;
			 ::GetWindowRect(hwnd, &rect);
			 ::GetWindowRect(hwnd2, &rect2);

			 w = rect.right - rect.left;
			 h = rect.bottom - rect.top;	

			 w2 = rect2.right - rect2.left;
			 h2 = rect2.bottom - rect2.top;	

			 // 下面这段查MSDN的BitBlt函数，后面有一个 Capturing an Image，大致有下面一段
			 hdc = ::GetWindowDC(hwnd);	
			 hdcCompatible = ::CreateCompatibleDC(hdc);
			 hbm = ::CreateCompatibleBitmap(hdc, w, h);
			 ::SelectObject(hdcCompatible, hbm);

			 hdc2 = ::GetWindowDC(hwnd2);	
			 hdcCompatible2 = ::CreateCompatibleDC(hdc2);
			 hbm2 = ::CreateCompatibleBitmap(hdc2, w2, h2);
			 ::SelectObject(hdcCompatible2, hbm2);

			 //unsigned char * data = new unsigned char[w*h*4];
			 //unsigned char * data1 = new unsigned char[w*h*3/2];

			 // 给GetDIBits用的结构体 
			 //BITMAPINFO infoHeader;
			 memset(&infoHeader.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
			 infoHeader.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			 infoHeader.bmiHeader.biWidth = w;
			 infoHeader.bmiHeader.biHeight = h;
			 infoHeader.bmiHeader.biPlanes = 1;
			 infoHeader.bmiHeader.biBitCount = 32; // 这里建议用32，经过测试在我的机器上比24速度快比较多
			 infoHeader.bmiHeader.biCompression = BI_RGB;	

			 //BITMAPINFO infoHeader;
			 memset(&infoHeader2.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
			 infoHeader2.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			 infoHeader2.bmiHeader.biWidth = w2;
			 infoHeader2.bmiHeader.biHeight = h2;
			 infoHeader2.bmiHeader.biPlanes = 1;
			 infoHeader2.bmiHeader.biBitCount = 32; // 这里建议用32，经过测试在我的机器上比24速度快比较多
			 infoHeader2.bmiHeader.biCompression = BI_RGB;	

		 }


};
}


array<unsigned char>^ ObjectToByteArray(System::Object ^_Object)
{
	try
	{
		// create new memory stream
		System::IO::MemoryStream ^_MemoryStream = gcnew System::IO::MemoryStream();

		// create new BinaryFormatter
		System::Runtime::Serialization::Formatters::Binary::BinaryFormatter^_BinaryFormatter = gcnew System::Runtime::Serialization::Formatters::Binary::BinaryFormatter();
		
		// Serializes an object, or graph of connected objects, to the given stream.
		_BinaryFormatter->Serialize(_MemoryStream, _Object);
		
		// convert stream to byte array and return
		array<unsigned char>^ p_char = _MemoryStream->GetBuffer();
		return p_char;

	}
	catch (...)
	{
		// Error
		//Console::WriteLine("Exception caught in process: {0}", _Exception->ToString());
	}
	// Error occured, return null
	return nullptr;
}
